﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Net;
using Common;
using System.Data;
using SDK;
using eBay;

namespace eBay {
    public static class eBayRequest {
        public static DataSet SendRequest(HttpWebRequest request, byte[] data) {
            Stream str = null;
            try {
                //Set the request Stream
                str = request.GetRequestStream();
                //Write the equest to the Request Steam
                str.Write(data, 0, data.Length);
                str.Close();
                //Get response into stream
                WebResponse resp = request.GetResponse();
                str = resp.GetResponseStream();
            }
            catch (WebException wEx) {
                //Error has occured whilst requesting
                //Display error message and exit.
                // TODO: надо бы ругнуться пользователю или в лог
                if (wEx.Status == WebExceptionStatus.Timeout) {
                    return null;
                }
                else {
                    return null;
                }
            }


            StreamReader sr = new StreamReader(str);
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(sr.ReadToEnd());
            sr.Close();
            str.Close();

            string tmpFileName = SDK.Funcs.GetTempFileName();
            xmlDoc.Save(tmpFileName);
            DataSet ds = new DataSet();
            ds.ReadXml(tmpFileName);
            File.Delete(tmpFileName);
            return ds;
        }

        public static HttpWebRequest SetupRequest(string CallName, long ContentLength, int APICompatibilityLevel) {
            return SetupRequest(CallName, ContentLength, APICompatibilityLevel, 581, Global.Configuration.ServerUrl, APITypes.NotSet);
        }

        public static HttpWebRequest SetupRequest(string CallName, long ContentLength, int APICompatibilityLevel, int eBayAPIVersion, string APIUrl) {
            return SetupRequest(CallName, ContentLength, APICompatibilityLevel, eBayAPIVersion, APIUrl, APITypes.NotSet);
        }

        public static HttpWebRequest SetupRequest(string CallName, long ContentLength, int APICompatibilityLevel, int eBayAPIVersion, string APIUrl, APITypes type) {
            //Create a new HttpWebRequest object for the ServerUrl
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(APIUrl);

            //Set Request Method (POST) and Content Type (text/xml)
            request.Method = "POST";
            request.ContentType = "text/xml";
            request.ContentLength = ContentLength;

            if (type == APITypes.FindingAPI) {
                request.Headers.Add("X-EBAY-SOA-SERVICE-NAME", "FindingService");
                request.Headers.Add("X-EBAY-SOA-OPERATION-NAME", CallName);
                request.Headers.Add("X-EBAY-SOA-SERVICE-VERSION", "1.4.0");
                request.Headers.Add("X-EBAY-SOA-GLOBAL-ID", "EBAY-US");
                request.Headers.Add("X-EBAY-SOA-SECURITY-APPNAME", Global.Configuration.AppIDProduct);
                request.Headers.Add("X-EBAY-SOA-REQUEST-DATA-FORMAT", "XML");
            }
            else {
                //Add the Keys to the HTTP Headers
                request.Headers.Add("X-EBAY-API-DEV-NAME: " + Global.Configuration.DevID);
                request.Headers.Add("X-EBAY-API-APP-NAME: " + Global.Configuration.AppIDSandbox);
                request.Headers.Add("X-EBAY-API-CERT-NAME: " + Global.Configuration.CertID);

                //Add Compatability Level to HTTP Headers
                //Regulates versioning of the XML interface for the API
                request.Headers.Add("X-EBAY-API-COMPATIBILITY-LEVEL: " + APICompatibilityLevel);

                //Add function name, SiteID and Detail Level to HTTP Headers
                request.Headers.Add("X-EBAY-API-CALL-NAME: " + CallName);
                request.Headers.Add("X-EBAY-API-SITEID: " + Global.Configuration.SiteID);


                request.Headers.Add("X-EBAY-API-VERSION: " + eBayAPIVersion);
                request.Headers.Add("X-EBAY-API-REQUEST-ENCODING: XML");
                request.Headers.Add("X-EBAY-API-RESPONSE-ENCODING: XML");
            }

            //Time out = 15 seconds,  set to -1 for no timeout.
            //If times-out - throws a WebException with the
            //Status property set to WebExceptionStatus.Timeout.
            request.Timeout = 15000;
            return request;
        }
    }

    public class eBayRequestType {

        #region Protected Fields
        protected HttpWebRequest InnerRequest;
        protected string InnerRequestName;
        protected XmlDocument InnerXmlDoc;
        protected byte[] InnerContent;
        #endregion

        public eBayRequestType(string requestName, string APIUrl) {
            this.InnerRequest = (HttpWebRequest)WebRequest.Create(APIUrl);
            this.InnerRequestName = requestName;
            this.InnerXmlDoc = new XmlDocument();

            if (!String.IsNullOrEmpty(requestName))
                this.InnerXmlDoc.Load(Common.Funcs.GetAppPath() + "APICalls\\" + InnerRequestName + ".xml");
        }

        #region Protected Methods
        protected virtual void SetupHeaders() {
            InnerRequest.Method = "POST";
            InnerRequest.ContentType = "text/xml";
            InnerRequest.ContentLength = InnerContent.Length;
            InnerRequest.Timeout = 15000;
        }
        #endregion

        #region Public Methods
        public virtual object Execute() {
            //Get XML into a string for use in encoding
            string xmlText = XmlDoc.InnerXml;
            //Put the data into a UTF8 encoded  byte array
            UTF8Encoding encoding = new UTF8Encoding();
            int dataLen = encoding.GetByteCount(xmlText);
            InnerContent = new byte[dataLen];
            Encoding.UTF8.GetBytes(xmlText, 0, xmlText.Length, InnerContent, 0);

            SetupHeaders();

            Stream str = null;
            try {
                //Set the request Stream
                str = InnerRequest.GetRequestStream();
                //Write the equest to the Request Steam
                str.Write(InnerContent, 0, InnerContent.Length);
                str.Close();
                //Get response into stream
                WebResponse resp = InnerRequest.GetResponse();
                str = resp.GetResponseStream();
            }
            catch (WebException wEx) {
                //Error has occured whilst requesting
                //Display error message and exit.
                // TODO: надо бы ругнуться пользователю или в лог
                if (wEx.Status == WebExceptionStatus.Timeout) {
                    return null;
                }
                else {
                    return null;
                }
            }


            StreamReader sr = new StreamReader(str);
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(sr.ReadToEnd());
            sr.Close();
            str.Close();

            string tmpFileName = SDK.Funcs.GetTempFileName();
            xmlDoc.Save(tmpFileName);
            DataSet ds = new DataSet();
            ds.ReadXml(tmpFileName);
            File.Delete(tmpFileName);

            return ds;
        }
        #endregion

        #region Public Properties
        public string RequestName {
            get { return InnerRequestName; }
            set { InnerRequestName = value; }
        }
        public HttpWebRequest Request {
            get { return this.InnerRequest; }
        }
        public XmlDocument XmlDoc {
            get { return InnerXmlDoc; }
            set { InnerXmlDoc = value; }
        }
        #endregion
    }

    public class FindItemsRequestType : eBayRequestType {

        #region Protected Fields
        private string InnerQueryKeywords;
        private SortOrderCodeType InnerSortOrder;
        private int InnerMaxEntries;
        private bool InnerHideDuplicateItems;
        private string InnerPostalCode;
        private SimpleItemSortCodeType InnerItemSort;
        #endregion

        public FindItemsRequestType() : base("FindItemsRequest", Global.Configuration.ShoppingAPIUrl) { }

        #region Protected Methods

        protected override void SetupHeaders() {
            base.SetupHeaders();

            //Add the Keys to the HTTP Headers
            InnerRequest.Headers.Add("X-EBAY-API-DEV-NAME", Global.Configuration.DevID);
            InnerRequest.Headers.Add("X-EBAY-API-APP-NAME", Global.Configuration.AppIDSandbox);
            InnerRequest.Headers.Add("X-EBAY-API-CERT-NAME", Global.Configuration.CertID);

            //Add Compatability Level to HTTP Headers
            //Regulates versioning of the XML interface for the API
            InnerRequest.Headers.Add("X-EBAY-API-COMPATIBILITY-LEVEL", "581");
            InnerRequest.Headers.Add("X-EBAY-API-VERSION", "581");

            //Add function name, SiteID and Detail Level to HTTP Headers
            InnerRequest.Headers.Add("X-EBAY-API-CALL-NAME", "FindItems");
            InnerRequest.Headers.Add("X-EBAY-API-SITEID", Global.Configuration.SiteID);
            InnerRequest.Headers.Add("X-EBAY-API-REQUEST-ENCODING", "XML");
            InnerRequest.Headers.Add("X-EBAY-API-RESPONSE-ENCODING", "XML");

            //InnerRequest.Headers.Add("X-EBAY-SOA-SERVICE-NAME", "FindingService");
            //InnerRequest.Headers.Add("X-EBAY-SOA-OPERATION-NAME", "FindItems");
            //InnerRequest.Headers.Add("X-EBAY-SOA-SERVICE-VERSION", "1.4.0");
            //InnerRequest.Headers.Add("X-EBAY-SOA-GLOBAL-ID", "EBAY-US");
            //InnerRequest.Headers.Add("X-EBAY-SOA-SECURITY-APPNAME", Global.Configuration.AppIDProduct);
            //InnerRequest.Headers.Add("X-EBAY-SOA-REQUEST-DATA-FORMAT", "XML");
        }

        #endregion

        #region Public Methods
        public override object Execute() {
            return new FindItemsResponseType((DataSet)base.Execute());
        }
        #endregion

        #region Public Properties
        public string QueryKeywords {
            get { return InnerQueryKeywords; }
            set {
                XmlNode root = XmlDoc[RequestName];

                if (root.SelectNodes("QueryKeywords").Count == 0) {
                    if (!String.IsNullOrEmpty(value))
                        root.InnerXml += "<QueryKeywords>" + value + "</QueryKeywords>";
                }
                else {
                    XmlNode node = root["QueryKeywords"];
                    node.InnerText = value;
                }

                InnerQueryKeywords = value;
            }
        }
        public SortOrderCodeType SortOrder {
            get { return InnerSortOrder; }
            set {
                XmlNode root = XmlDoc[RequestName];

                if (root.SelectNodes("SortOrder").Count == 0) {
                    if (value != SortOrderCodeType.NotSet)
                        root.InnerXml += "<SortOrder>" + value.ToString() + "</SortOrder>";
                }
                else {
                    XmlNode node = root["SortOrder"];
                    node.InnerText = value.ToString();
                }

                InnerSortOrder = value;
            }
        }
        public int MaxEntries {
            get { return InnerMaxEntries; }
            set {
                XmlNode root = XmlDoc[RequestName];

                if (root.SelectNodes("MaxEntries").Count == 0) {
                    if (value > 0)
                        root.InnerXml += "<MaxEntries>" + value + "</MaxEntries>";
                }
                else {
                    XmlNode node = root["MaxEntries"];
                    node.InnerText = value + "";
                }

                InnerMaxEntries = value;
            }
        }
        public bool HideDuplicateItems {
            get { return InnerHideDuplicateItems; }
            set {
                XmlNode root = XmlDoc[RequestName];

                if (root.SelectNodes("HideDuplicateItems").Count == 0)
                    root.InnerXml += "<HideDuplicateItems>" + value + "</HideDuplicateItems>";

                InnerHideDuplicateItems = value;
            }
        }
        public string PostalCode {
            get { return InnerPostalCode; }
            set {
                XmlNode root = XmlDoc[RequestName];

                if (root.SelectNodes("PostalCode").Count == 0) {
                    if (!String.IsNullOrEmpty(value))
                        root.InnerXml += "<PostalCode>" + value + "</PostalCode>";
                }
                else {
                    XmlNode node = root["PostalCode"];
                    node.InnerText = value;
                }

                InnerPostalCode = value;
            }
        }
        public SimpleItemSortCodeType ItemSort {
            get { return InnerItemSort; }
            set {
                XmlNode root = XmlDoc[RequestName];

                if (root.SelectNodes("ItemSort").Count == 0) {
                    if (value != SimpleItemSortCodeType.NotSet)
                        root.InnerXml += "<ItemSort>" + value.ToString() + "</ItemSort>";
                    
                }
                else {
                    XmlNode node = root["ItemSort"];
                    node.InnerText = value.ToString();
                }

                InnerItemSort = value;
            }
        }
        #endregion
    }

}
